#include "Executor.h"

vector<Task*> Executor::taskList;
enum Executor::COMMAND_TYPE;
enum Executor::KEYWORD_TYPE;

int main()
{
        //UI output;
        Executor execute;
        //Storage store;
        string inputLine;
                
        //output.printMessage("welcome");
        cout << "Welcome" << endl;									//temp

        while (true) {
                //output.printMessage("enter task");
                cout << "enter task:" << endl;						//temp
                getline(cin, inputLine);
                string feedback = execute.executeCommand(inputLine);
                //output.printMessage(feedback);        
                cout << feedback << endl;							//temp
                //store.saveTask();
        }

        return 0;
}

Executor::COMMAND_TYPE Executor::determineCommandType(string commandTypeString)
{
        if(commandTypeString == "add") {
                return COMMAND_TYPE::ADD;
        } else if (commandTypeString == "delete") {
                return COMMAND_TYPE::DELETE;
        } else if (commandTypeString == "show") {
                return COMMAND_TYPE::SHOW;
        } else {
                return COMMAND_TYPE::INVALID;
        }
}

Executor::KEYWORD_TYPE Executor::determineKeywordType(string keywordTypeString)
{
        if(keywordTypeString == "DATE")
                return KEYWORD_TYPE::DATE;
		if(keywordTypeString == "STARTS")
                return KEYWORD_TYPE::STARTS;
		if(keywordTypeString == "ENDS")
                return KEYWORD_TYPE::ENDS;
        if(keywordTypeString == "DETAIL")
                return KEYWORD_TYPE::DETAIL;
}

string Executor::getFirstWord(string &inputLine) {
        string firstWord = inputLine.substr(0, inputLine.find(' '));
        return firstWord;
}

string Executor::removeFirstWord(string &inputLine){
        int i = inputLine.find(' ');
        if(i != -1)
                inputLine.erase(0, i+1);
        else
                inputLine.clear();

        return inputLine;
}

string Executor::executeCommand(string &inputLine)
{
        string commandTypeString = getFirstWord(inputLine);
		removeFirstWord(inputLine);             // to remove '[command]' from the inputLine
        COMMAND_TYPE commandType = determineCommandType(commandTypeString);

        switch (commandType) {
        case ADD: 
                return executeAdd(inputLine);
        case DELETE: 
                return executeDelete(inputLine);
        case SHOW: 
                return executeShow(inputLine);
        case INVALID:
                return executeInvalid(inputLine);
        }
}

string Executor::makeTask(string &inputLine, Task* &t)
{
        Validator checker;
        string response = "Task Formatted";

        string name = getFirstWord(inputLine);
        removeFirstWord(inputLine);
        //if(checker.isValidName(name))
        int i = 1;									//temp
        if(i == 1)									//temp
        {
                t->appendToName(name);
                while(!inputLine.empty())
                {
                        string followingWord = getFirstWord(inputLine);
                        removeFirstWord(inputLine);

                        if(checker.isValidKeyword(followingWord)) {
                                KEYWORD_TYPE keywordType = determineKeywordType(followingWord);

                                switch(keywordType) 
                                {
                                case DATE:
									{
                                        string date = getFirstWord(inputLine);
                                        removeFirstWord(inputLine);
                                        if(checker.isValidDate(date))
                                                t->setDate(date);
                                        else
                                                //response = output.generateMessage("invalidDate", date);
                                                response = "invalidDate";				//temp
                                        break;
									}
								case STARTS:
									{
										string st_time = getFirstWord(inputLine);
										removeFirstWord(inputLine);
										if(1)			//checker.isValidTime(st_time))
											 t->setStartTime(makeInt(st_time));
                                        else
                                                //response = output.generateMessage("invalidTime", date);
                                                response = "invalidTime";				//temp
                                        break;
									}
								case ENDS:
									{
										string end_time = getFirstWord(inputLine);
										removeFirstWord(inputLine);
										if(1)			//checker.isValidTime(end_time))
											 t->setEndTime(makeInt(end_time));
                                        else
                                                //response = output.generateMessage("invalidTime", date);
                                                response = "invalidTime";				//temp
                                        break;
									}
								case DETAIL:
									{
										do{
											string detail = getFirstWord(inputLine);
											removeFirstWord(inputLine);
											t->appendToDetail(detail);
										
											followingWord = getFirstWord(inputLine);
										}while(!checker.isValidKeyword(followingWord) && !inputLine.empty());
                                        break;
									}
								}

						}
                        else 
							t->appendToName(followingWord);
				}
        }
        else
                //response = output.generateMessage("invalidName", name);
                response = "invalidName";												//temp

        return response;
}

string Executor::executeAdd(string &inputLine) {

        //UI output;
        Task *t;
        //Storage store;
        string result, response;

        t = new Task();
        result = makeTask(inputLine, t);

        if(result == "Task Formatted")
        {
                taskList.push_back(t);
                // will return a generated/formatted string (i.e "Group Meeting at 5pm has been added")
                // am including the task, t, so that it uses the info of t to structure this above string
                //response = output.generateMessage("ADDED", t);
                response = "ADDED";													//temp
        }

        else
                response = result;

        return response;
}

int Executor::makeInt(string taskNum_str){

        return atoi(taskNum_str.c_str());
}

string Executor::executeDelete(string &inputLine) {

        //UI output;
        //Storage store;
        Validator checker;
        string response;

        string taskNum_str = getFirstWord(inputLine);
        if(checker.isInt(inputLine))
        {
                int taskNum_int = makeInt(taskNum_str);
                int actual_taskNum_int = taskNum_int - 1;
                if(checker.isValidTaskNumber(actual_taskNum_int, taskList))
                {       
                        string deletedTask = taskList[actual_taskNum_int]->getName();
                        taskList.erase(taskList.begin()+actual_taskNum_int);
                        // "deleted task num" string generated
                        //response = output.generateMessage("DELETED", deletedTask);
                        response = "DELETED";							//temp
                }
                else
                {       //invalid task num string generated
                        //response = output.generateMessage("invalidTaskNum", taskNum_int); 
                        response = "invalidTaskNum";					//temp
                }
        }
        else
        {       //"not an int" string generated
                //response = output.generateMessage("notInt", inputLine);
                response = "notInt";									//temp
        }

        return response;
}

string Executor::executeInvalid(string &inputLine) {
        
        //UI output;

        //string response = output.generateMessage("invalidCommand", inputLine);
        string response = "invalidCommand dont have any execution";		//temp

        return response;
}

string Executor::executeShow(string &inputLine)
{
	Validator checker;
	string response;

	if(inputLine == "")					//isEmptyString(inputLine))
	{
		for(int i = 0; i < taskList.size(); i++)
			cout << i+1 << ". " << taskList[i]->getName() << TAB << taskList[i]->getDate() << endl;
	}
	else
	{
		string date = getFirstWord(inputLine);
		removeFirstWord(inputLine);
		if(checker.isValidDate(date))
		{
			for(int i = 0; i < taskList.size(); i++)
			{	
				if(date == taskList[i]->getDate())
					cout << i+1 << ". " << taskList[i]->getName() << TAB << taskList[i]->getDate() << endl;
			}
		}
		else
			//response = output.generateMessage("invalidDate", date);
			response = "invalidDate";				//temp
		}
	
	return EMPTY;
}